package com.uinnova.product.eam.service.impl;

import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.service.es.IamsESCIDesignSvc;
import com.uinnova.product.eam.service.es.IamsESCIHistoryDesignSvc;
import com.uinnova.product.eam.service.es.IamsESCmdbCommDesignSvc;
import com.uino.api.client.cmdb.ICIHistoryApiSvc;
import com.uino.bean.cmdb.base.ESCIHistoryInfo;
import com.uino.bean.cmdb.base.ESCIHistoryInfo.ActionType;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.query.ESCIHistorySearchBean;
import com.uino.dao.cmdb.ESCISvc;
import com.uino.util.sys.BeanUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * CI历史服务
 * 
 * @author zoumengjie
 *
 */
@Service
public class IamsCIHistoryDesignSvc implements ICIHistoryApiSvc {

    @Autowired
    private IamsESCIHistoryDesignSvc ciHistorySvc;

    @Autowired
    private IamsESCmdbCommDesignSvc commSvc;

    @Autowired
    private IamsESCIDesignSvc esCiSvc;

    @Autowired
    private ESCISvc esciSvc;

    public Long saveOrUpdate(ESCIInfo ciInfo, ActionType action) {
        return ciHistorySvc.saveOrUpdateHistoryInfo(ciInfo, action);
    }

    public Integer saveOrUpdateBatch(List<ESCIInfo> ciInfos, ActionType action) {
        if (!BinaryUtils.isEmpty(ciInfos)) {
            return ciHistorySvc.saveOrUpdateHistoryInfosBatch(ciInfos, action);
        }
        return 1;
    }

    @Override
    public ESCIHistoryInfo getCIInfoHistoryByCIVersion(String ciCode, Long classId, Long version) {
        Assert.notNull(ciCode, "X_PARAM_NOT_NULL${name:ciCode}");
        Assert.notNull(classId, "X_PARAM_NOT_NULL${name:classId}");
        Assert.notNull(version, "X_PARAM_NOT_NULL${name:version}");
        ESCIHistorySearchBean bean = ESCIHistorySearchBean.builder().ciCode(ciCode).classId(classId).version(version).build();
        QueryBuilder query = this.getQueryBuilderByBean(bean);
        List<ESCIHistoryInfo> ciInfos = ciHistorySvc.getListByQuery(query);
        Assert.isTrue(!BinaryUtils.isEmpty(ciInfos), "该CI版本不存在");
        ESCIHistoryInfo historyInfo = ciInfos.get(0);
        ESCIInfo esciInfo = BeanUtil.converBean(historyInfo, ESCIInfo.class);
        esCiSvc.transCIAttrs(Collections.singletonList(esciInfo), true);
        historyInfo.setAttrs(esciInfo.getAttrs());
        return historyInfo;
    }

    public List<ESCIHistoryInfo> getCIInfoHistoryByCICode(String ciCode, Long classId) {
        Assert.notNull(ciCode, "X_PARAM_NOT_NULL${name:ciCode}");
        Assert.notNull(classId, "X_PARAM_NOT_NULL${name:classId}");
        ESCIHistorySearchBean bean = ESCIHistorySearchBean.builder().ciCode(ciCode).classId(classId).build();
        QueryBuilder query = this.getQueryBuilderByBean(bean);
        long count = ciHistorySvc.countByCondition(query);
        List<ESCIHistoryInfo> historyInfos = ciHistorySvc.getSortListByQuery(1, new BigDecimal(count).intValue(), query, "version", false).getData();
        if (!BinaryUtils.isEmpty(historyInfos)) {
            Map<Long, ESCIHistoryInfo> historyMap = BinaryUtils.toObjectMap(historyInfos, "version");
            List<ESCIInfo> esciInfos = BeanUtil.converBean(historyInfos, ESCIInfo.class);
            esCiSvc.transCIAttrs(esciInfos, true);
            esciInfos.forEach(ciInfo -> {
                ESCIHistoryInfo historyInfo = historyMap.get(ciInfo.getVersion());
                historyInfo.setAttrs(ciInfo.getAttrs());
            });
            return historyInfos;
        }
        return new ArrayList<>();
    }

    public Page<ESCIHistoryInfo> getCIHistoryPageBySearchBean(ESCIHistorySearchBean bean) {
        Assert.notNull(bean, "X_PARAM_NOT_NULL${name:searchBean}");
        QueryBuilder query = this.getQueryBuilderByBean(bean);
        Page<ESCIHistoryInfo> esPage = ciHistorySvc.getSortListByQuery(bean.getPageNum(), bean.getPageSize(), query, "version", false);
        List<ESCIHistoryInfo> historyInfos = esPage.getData();
        if (!BinaryUtils.isEmpty(historyInfos)) {
            Map<Long, ESCIHistoryInfo> historyMap = BinaryUtils.toObjectMap(historyInfos, "version");
            List<ESCIInfo> esciInfos = BeanUtil.converBean(historyInfos, ESCIInfo.class);
            esCiSvc.transCIAttrs(esciInfos, true);
            esciInfos.forEach(ciInfo -> {
                ESCIHistoryInfo historyInfo = historyMap.get(ciInfo.getVersion());
                historyInfo.setAttrs(ciInfo.getAttrs());
            });
        }
        return esPage;
    }

    @Override
    public void delAll(List<Long> classIds) {
        if(BinaryUtils.isEmpty(classIds)){
            return;
        }
        ciHistorySvc.deleteByQuery(QueryBuilders.termsQuery("classId", classIds), true);
    }

    @Override
    public List<String> getCIVersionList(String ciCode, Long classId) {
        Assert.notNull(ciCode, "X_PARAM_NOT_NULL${name:ciCode}");
        Assert.notNull(classId, "X_PARAM_NOT_NULL${name:classId}");
        List<String> res = new ArrayList<>();
        ESCIHistorySearchBean bean = ESCIHistorySearchBean.builder().ciCode(ciCode).classId(classId).build();
        QueryBuilder query = this.getQueryBuilderByBean(bean);
        long count = ciHistorySvc.countByCondition(query);
        if (count > 0) {
            List<ESCIHistoryInfo> esciHistoryInfos = ciHistorySvc.getSortListByQuery(1, new BigDecimal(count).intValue(), query, "version", false).getData();
            for (ESCIHistoryInfo historyInfo : esciHistoryInfos) {
                if (historyInfo.getVersion() != null) {
                    res.add(historyInfo.getVersion() + "-" + historyInfo.getCreateTime());
                }
            }
        }
        if (res.size() > 1) {
            res.remove(0);
        }
        return res;
    }

    private QueryBuilder getQueryBuilderByBean(ESCIHistorySearchBean bean) {
        // 组装查询条件
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        if (bean.getCiId() != null) {
            query.must(QueryBuilders.termQuery("id", bean.getCiId()));
        }
        if (bean.getClassId() != null) {
            query.must(QueryBuilders.termQuery("classId", bean.getClassId()));
        }
        if (bean.getCiCode() != null) {
            query.must(QueryBuilders.termQuery("ciCode.keyword", bean.getCiCode()));
        }
        if (bean.getVersion() != null) {
            query.must(QueryBuilders.termQuery("version", bean.getVersion()));
        }
        return query;
    }


    @Override
    public List<ESCIHistoryInfo> bathGetCIInfoHistoryByCIVersion(Map<String, Long> ciCodeVersionMap) {
        if (CollectionUtils.isEmpty(ciCodeVersionMap)) {
            return Collections.emptyList();
        }

        BoolQueryBuilder query = QueryBuilders.boolQuery();
        for (Map.Entry<String, Long> entry : ciCodeVersionMap.entrySet()) {
            BoolQueryBuilder subQuery = QueryBuilders.boolQuery();
            subQuery.must(QueryBuilders.termQuery("ciCode.keyword", entry.getKey()));
            subQuery.must(QueryBuilders.termQuery("version", entry.getValue()));
            query.should(subQuery);
        }
        List<ESCIHistoryInfo> ciInfos = ciHistorySvc.getListByQuery(query);

        esciSvc.transCIHistoryAttrs(ciInfos, true);
        return ciInfos;
    }
}
